/**
 * 应用配置类型定义
 *
 * @fileoverview 定义应用程序各种配置项的类型结构，包括代理、监控、网络、
 * 预约、日志等模块的配置参数。确保配置数据的类型安全和一致性。
 *
 * 主要配置模块：
 * - 代理配置（ProxyConfig）- 网络代理和轮换策略
 * - 监控配置（MonitoringConfig）- 自动监控和预约设置
 * - 网络配置（NetworkConfig）- HTTP请求和重试参数
 * - 预约配置（BookingConfig）- 预约流程和表单映射
 * - 日志配置（LoggingConfig）- 日志级别和输出设置
 * - 用户配置（AppConfig）- 应用程序主配置
 *
 * @author System
 * @version 1.0.0
 * @since 2024
 *
 * @example
 * ```typescript
 * import type { AppConfig, ProxyConfig } from './config'
 *
 * const config: AppConfig = {
 *   proxy: {
 *     enabled: true,
 *     provider: 'webshare',
 *     type: 'datacenter',
 *     protocol: 'http',
 *     // ... 其他配置
 *   }
 * }
 * ```
 */

import { validateDocumentNumber } from '../utils/doc-number'

// ============================================================================
// 代理配置类型
// ============================================================================

/**
 * 代理配置接口
 *
 * @description 定义网络代理的完整配置，包括代理池管理、轮换策略、
 * 认证信息等。支持多种代理类型和智能轮换机制。
 *
 * @interface ProxyConfig
 * @example
 * ```typescript
 * const proxyConfig: ProxyConfig = {
 *   enabled: true,
 *   provider: 'webshare',
 *   type: 'datacenter',
 *   protocol: 'http',
 *   auth: {
 *     username: 'user123',
 *     password: 'pass456'
 *   },
 *   pool: ['192.168.1.1:8080', '192.168.1.2:8080'],
 *   rotate_mode: 'per_session',
 *   sticky_minutes: 10,
 *   rotate_on_errors: ['429', '403', 'ip_lock_512'],
 *   max_concurrent_sessions: 4
 * }
 * ```
 */
export interface ProxyConfig {
  /** 是否启用代理功能 */
  enabled: boolean
  /** 多服务商代理支持。统一入口，移除单一提供商与顶层池概念 */
  providers?: ProxyProvider[]
  /** 每个服务商参与轮换的活跃池上限（仅保存/使用该数量，避免载入过多） */
  max_active_pool_per_provider?: number
  /** 执行时全局参与轮换的代理条目上限（从合并后的代理集合中抽样） */
  max_proxies_overall?: number
  /** 是否在配置中保存完整下载列表（pool_full）。默认 false 以减少配置体积 */
  save_full_pool?: boolean
  /** 代理轮换模式：每会话轮换或每请求轮换 */
  rotate_mode: 'per_session' | 'per_request'
  /** 代理粘性时间（分钟），per_session模式下的保持时间 */
  sticky_minutes: number
  /** 触发代理轮换的错误码列表 */
  rotate_on_errors: string[]
  /** 最大并发会话数，防止过度使用代理资源 */
  max_concurrent_sessions: number
  /** 每个IP的最大并发租约数（用于ProxyLease机制，避免并发会话复用同一代理） */
  max_concurrent_per_ip?: number
  /** 启动或关键导航失败时，轮换代理的最大尝试次数（默认2-3） */
  max_proxy_attempts?: number
  /** 代理校验配置 */
  validation: ProxyValidationConfig
  /** 临时黑名单（按钮校验写入），到期自动失效 */
  temp_blacklist?: ProxyBlacklistEntry[]
  /** 黑名单有效期（分钟），默认60 */
  blacklist_ttl_minutes?: number
  /** 本月被判定为超额的服务商标记（可手动清除） */
  quota_exceeded?: ProxyQuotaExceededEntry[]
}

/**
 * 多服务商代理定义
 */
export interface ProxyProvider {
  /** 服务商标识（自定义 ID） */
  id: string
  /** 可读名称（可选） */
  label?: string
  /** 供应商类型（如 webshare、custom）。不填默认按现有字段推断 */
  vendor?: 'webshare' | 'custom'
  /** 套餐/计划类型（用于行为差异化） */
  plan_kind?: 'dynamic_short' | 'static_long' | 'fixed'
  /** 代理类型 */
  type: 'datacenter' | 'residential' | 'dynamic_pool'
  /** 协议 */
  protocol: 'http' | 'https' | 'socks5'
  /** 认证（可选，某些免费池可能无需账号） */
  auth?: {
    username: string
    password: string
  }
  /** 服务商帐号，一般是邮箱，用于找回邮箱 */
  account?: string
  /** WebShare API Key（用于调用列表/统计等接口，Authorization: Token KEY） */
  api_key?: string
  /** 是否免费类型（用于自动命名与策略） */
  is_free?: boolean
  /** IP 池 */
  pool: string[]
  /** 原始代理条目（含用户名/密码），例如 ip:port:username:password。用于需要会话/账号维度的场景 */
  pool_full?: string[]
  /** 下载得到的池总条数（仅统计用） */
  pool_total?: number
  /** 池最近刷新时间戳（ms），动态短效池用于TTL控制 */
  pool_refreshed_at?: number
  /** 是否启用该服务商（默认启用） */
  enabled?: boolean
  /** 覆盖行内凭据：如果为 true，则忽略池条目中的 username:password，统一使用 provider.auth */
  force_auth_from_config?: boolean
  /** WebShare Plan ID（可选） */
  plan_id?: string
  /** 动态短效池：IP失效时间（秒），例如 180（3分钟） */
  pool_ttl_seconds?: number
  /** 动态短效池：自动刷新间隔（秒），例如 120（2分钟），用于前端定时按钮或外部调度 */
  auto_refresh_seconds?: number
}

/**
 * 按月的流量超额标记条目
 */
export interface ProxyQuotaExceededEntry {
  /** 服务商ID（对应 providers[].id） */
  provider_id: string
  /** 月份，格式 YYYY-MM */
  month: string
  /** 备注原因（可选） */
  reason?: string
  /** 标记时间戳（ms） */
  marked_at: number
}

/**
 * 代理校验配置
 *
 * @description 启动前或切换代理时的连通性/鉴权快速校验。
 */
export interface ProxyValidationConfig {
  /** 是否启用代理校验 */
  enabled: boolean
  /** 校验目标URL（建议与业务同域，HTTPS 将触发 CONNECT 隧道） */
  test_url: string
  /** 超时时间（秒） */
  timeout_seconds: number
  /** 期望HTTP状态码（默认200） */
  expect_status?: number
}

/**
 * 代理临时黑名单条目
 */
export interface ProxyBlacklistEntry {
  /** 形如 protocol://ip:port，与自动化内的 server 一致 */
  server: string
  /** 到期时间戳（ms），到期后应忽略 */
  until: number
  /** 最近一次检测时间戳（ms） */
  lastCheckedAt?: number
  /** 拉黑原因（如超时、407、状态码不匹配等） */
  reason?: string
}

// ============================================================================
// 监控配置类型
// ============================================================================

/**
 * 监控配置接口
 *
 * @description 定义自动监控和预约功能的配置参数，包括检查间隔、
 * 自动预约策略、身份池管理等。
 *
 */
export interface MonitoringConfig {
}

// ============================================================================
// 网络配置类型
// ============================================================================

/**
 * 网络配置接口
 *
 * @description 定义HTTP请求相关的配置，包括基础URL、用户代理、
 * 超时设置、重试策略等。
 *
 * @interface NetworkConfig
 * @example
 * ```typescript
 * const networkConfig: NetworkConfig = {
 *   base_url: 'https://api.example.com',
 *   base_urls: ['https://api1.example.com', 'https://api2.example.com'],
 *   request_timeout_seconds: 30,
 *   global_min_interval_seconds: 1.2
 * }
 * ```
 */
export interface NetworkConfig {
  /** 主要基础URL */
  base_url: string
  /** 备用基础URL列表，用于负载均衡或故障切换 */
  base_urls?: string[]
  /** 用户代理：已废弃。请使用记录级 user_agent 或运行期生成 */
  // user_agent?: string
  /** 是否拦截非关键静态资源（图片/媒体/字体/分析脚本等），以提速与省流量 */
  block_resources?: boolean
  /** 请求超时时间（秒） */
  request_timeout_seconds: number
  /** 全局最小请求间隔（秒），防止请求过于频繁 */
  global_min_interval_seconds: number
  /** 每个域名最大连接数（仅undici模式有效） */
  max_connections_per_host?: number
  /** 是否使用undici作为HTTP客户端（默认true，性能更好） */
  use_undici?: boolean
}

// ============================================================================
// 预约配置类型
// ============================================================================

/**
 * 多进程配置接口
 *
 * @description 定义多进程预约架构的配置参数
 */
export interface MultiprocessConfig {
  /** 是否启用多进程模式 */
  enabled: boolean
  /** 最大 Worker 进程数（默认50，与易语言工具一致） */
  maxWorkers?: number
  /** 最小 Worker 进程数（默认3，保证基本可用） */
  minWorkers?: number
  /** Worker 超时时间（毫秒） */
  workerTimeout?: number
  /** 健康检查间隔（毫秒） */
  healthCheckInterval?: number
  /** 默认模式（request/playwright） */
  defaultMode?: 'request' | 'playwright'
  /** 是否在 Request 失败时降级到 Playwright */
  fallbackToPlaywright?: boolean
}

/**
 * 预约配置接口
 *
 * @description 定义预约流程相关的配置，包括搜索范围、服务类型、
 * 表单映射、人性化延迟等参数。
 *
 * @interface BookingConfig
 * @example
 * ```typescript
 * const bookingConfig: BookingConfig = {
 *   available_window_days: 70,
 *   service_type: 'DI',
 *   default_office_code: 'HKLO',
 *   human_like_delays: {
 *     page_view_delay: { min: 2.0, max: 4.0 },
 *     pre_submit_delay: { min: 2.0, max: 3.0 }
 *   },
 *   multiprocess: {
 *     enabled: true,
 *     maxWorkers: 50
 *   }
 * }
 * ```
 */
export interface BookingConfig {
  /** 可用时间窗口天数 */
  available_window_days: number
  /** 服务类型代码（如：DI表示驾照相关服务） */
  service_type: string
  /** 默认办公地点代码 */
  default_office_code: string
  /** 人性化延迟配置，模拟真实用户行为 */
  human_like_delays: {
    /** 页面浏览延迟范围（秒） */
    page_view_delay: { min: number, max: number }
    /** 提交前延迟范围（秒） */
    pre_submit_delay: { min: number, max: number }
  }
  /** 多进程配置（可选） */
  multiprocess?: MultiprocessConfig
}

// ============================================================================
// 日志配置类型
// ============================================================================

/**
 * 日志配置接口
 *
 * @description 定义应用程序日志系统的配置，包括日志级别、输出方式、
 * 文件轮转、抽样策略、指标收集等功能。
 *
 * @interface LoggingConfig
 * @example
 * ```typescript
 * const loggingConfig: LoggingConfig = {
 *   log_level: 'INFO',
 *   log_retention: '7 days',
 *   console_output: true,
 *   file_output: true,
 *   save_html: true,
 *   save_snapshots: true,
 *   sampling: {
 *     enabled: true,
 *     debug_sample_rate: 0.1,
 *     info_sample_rate: 1.0,
 *     warn_sample_rate: 1.0
 *   },
 *   metrics: {
 *     enabled: true,
 *     reset_interval_hours: 24
 *   }
 * }
 * ```
 */
export interface LoggingConfig {
  /** 日志级别：DEBUG < INFO < WARN < ERROR */
  log_level: 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'
  /** 日志保留时间（如：7d, 30d, 1y） */
  log_retention: string
  /** 是否输出到控制台 */
  console_output: boolean
  /** 是否输出到文件 */
  file_output: boolean
  /** 是否保存HTML到磁盘（统一：请求/自动化均复用此开关） */
  save_html: boolean
  /** 是否保存快照/截图到磁盘（统一：自动化/工具均复用此开关） */
  save_snapshots: boolean
  /** 日志抽样配置，用于高频日志的性能优化 */
  sampling: {
    /** 是否启用抽样功能 */
    enabled: boolean
    /** DEBUG级别日志抽样率（0-1） */
    debug_sample_rate: number
    /** INFO级别日志抽样率（0-1） */
    info_sample_rate: number
    /** WARN级别日志抽样率（0-1） */
    warn_sample_rate: number
  }
  /** 指标收集配置 */
  metrics: {
    /** 是否启用指标收集 */
    enabled: boolean
    /** 指标重置间隔（小时） */
    reset_interval_hours: number
  }
  /** 是否在每次运行结束后压缩快照至每日归档 */
  archive_snapshots_enabled?: boolean
  /** 是否包含当天快照进入归档（默认仅归档历史日） */
  archive_snapshots_today?: boolean
  /** 归档成功后是否删除原始目录（默认否） */
  remove_original_snapshots_after_archive?: boolean
}

// ============================================================================
// 提醒配置类型
// ============================================================================

/**
 * 提醒配置接口
 *
 * @description 控制可预约提醒的行为，包括去重、免打扰与触发阈值等。
 */
export interface NotificationsConfig {
  // 提醒配置
}

// ============================================================================
// 应用主配置类型
// ============================================================================

/**
 * 应用程序主配置接口
 *
 * @description 包含应用程序所有模块的配置，是配置系统的根接口。
 * 整合了代理、监控、网络、预约、日志、GUI、功能特性等各个方面的设置。
 *
 * @interface AppConfig
 * @example
 * ```typescript
 * const appConfig: AppConfig = {
 *   proxy: proxyConfig,
 *   monitoring: monitoringConfig,
 *   network: networkConfig,
 *   booking: bookingConfig,
 *   logging: loggingConfig,
 *   notifications: notificationsConfig
 * }
 * ```
 */
export interface AppConfig {
  /** 代理配置 */
  proxy: ProxyConfig
  /** 监控配置 */
  monitoring: MonitoringConfig
  /** 网络配置 */
  network: NetworkConfig
  /** 预约配置 */
  booking: BookingConfig
  /** 日志配置 */
  logging: LoggingConfig
  /** 提醒配置 */
  notifications: NotificationsConfig
}

// ============================================================================
// 用户信息类型
// ============================================================================

/**
 * 用户信息接口
 *
 * @description 定义预约用户的基本信息结构，包括证件信息、联系方式、
 * 偏好设置等。用于身份池管理和预约数据填充。
 *
 * @interface UserInfo
 * @example
 * ```typescript
 * const userInfo: UserInfo = {
 *   passport_number: 'E12345678',
 *   license_number: '440123199001011234',
 *   license_owner_name: '张三',
 *   email: 'zhangsan@example.com',
 *   phone_number: '13800138000',
 *   issuing_country: 'CN',
 *   issuing_authority: 'GD',
 *   service_type: 'DI',
 *   preferred_dates: ['25-12-2024', '26-12-2024'],
 *   preferred_times: ['09:00-10:00', '14:00-15:00'],
 *   priority: 1
 * }
 * ```
 */
export interface UserInfo {
  /** 证件号码，规则：前缀(C/E，1-2位) + 数字(7-8位) 总长9 */
  passport_number: string
  /** 驾照号码，18位身份证号码 */
  license_number: string
  /** 驾照持有人姓名 */
  license_owner_name: string
  /** 电子邮箱地址 */
  email: string
  /** 联系电话号码 */
  phone_number: string
  /** 签发国家：CN-中国，OTH-其他 */
  issuing_country: 'CN' | 'OTH'
  /** 签发机关：GD-广东省，OTH-其他 */
  issuing_authority: 'GD' | 'OTH'
  /** 服务类型（可选） */
  service_type?: string
  /** 首选预约日期列表（可选） */
  preferred_dates?: string[]
  /** 首选预约时间列表（可选） */
  preferred_times?: string[]
  /** 优先级，1-5（可选） */
  priority?: number
}

/**
 * 批量用户数据接口
 *
 * @description 扩展UserInfo，添加批量处理相关的状态和元数据字段。
 * 用于批量预约功能中的用户数据管理。
 *
 * @interface BatchUserData
 * @extends UserInfo
 */
export interface BatchUserData extends UserInfo {
  /** 记录唯一标识（可选） */
  id?: string
  /** 处理状态 */
  status?: 'pending' | 'processing' | 'success' | 'failed'
  /** 错误信息（处理失败时） */
  error_message?: string
  /** 预约参考号（处理成功时） */
  reference_number?: string
  /** 创建时间 */
  created_at?: Date
  /** 更新时间 */
  updated_at?: Date
}

// ============================================================================
// 配置验证工具类
// ============================================================================

/**
 * 配置验证器类
 *
 * @description 提供配置数据的验证功能，确保配置项的有效性和一致性。
 * 包含用户信息验证和应用配置验证等静态方法。
 *
 * @class ConfigValidator
 * @example
 * ```typescript
 * // 验证用户信息
 * const userErrors = ConfigValidator.validateUserInfo(userInfo)
 * if (userErrors.length > 0) {
 *   console.error('用户信息验证失败:', userErrors)
 * }
 *
 * // 验证应用配置
 * const configErrors = ConfigValidator.validateConfig(appConfig)
 * if (configErrors.length > 0) {
 *   console.error('配置验证失败:', configErrors)
 * }
 * ```
 */
export class ConfigValidator {
  /**
   * 验证用户信息
   *
   * @description 验证UserInfo对象的各个字段是否符合业务规则和格式要求
   *
   * @param {UserInfo} user - 要验证的用户信息对象
   * @returns {string[]} 验证错误信息数组，空数组表示验证通过
   *
   * @example
   * ```typescript
   * const userInfo: UserInfo = {
   *   passport_number: 'E12345678',
   *   license_number: '440123199001011234',
   *   license_owner_name: '张三',
   *   email: 'zhangsan@example.com',
   *   // ... 其他字段
   * }
   *
   * const errors = ConfigValidator.validateUserInfo(userInfo)
   * if (errors.length > 0) {
   *   console.error('验证失败:', errors)
   * }
   * ```
   */
  static validateUserInfo(user: UserInfo): string[] {
    const errors: string[] = []

    // 证件号校验：C/E + (可为两位前缀) + 数字，整体9位
    if (!validateDocumentNumber(user.passport_number)) {
      errors.push('证件号格式不正确，应为 C/E 前缀 + 数字，总长9位')
    }

    if (!user.license_number || user.license_number.length !== 18) {
      errors.push('驾照号码应为18位')
    }

    if (!user.license_owner_name) {
      errors.push('驾照持有人姓名不能为空')
    }

    if (!user.email || !/@/.test(user.email)) {
      errors.push('邮箱格式不正确')
    }

    if (user.issuing_country === 'CN' && !['GD', 'OTH'].includes(user.issuing_authority)) {
      errors.push('中国内地驾照签发机关只支持 GD（广东省）或 OTH（其他省市）')
    }

    return errors
  }

  /**
   * 验证应用配置
   *
   * @description 验证AppConfig对象的各个模块配置是否合理和一致
   *
   * @param {AppConfig} config - 要验证的应用配置对象
   * @returns {string[]} 验证错误信息数组，空数组表示验证通过
   *
   * @example
   * ```typescript
   * const appConfig: AppConfig = {
   *   proxy: { enabled: true, pool: [] },
   *   monitoring: { check_interval_seconds: 5 },
   *   // ... 其他配置
   * }
   *
   * const errors = ConfigValidator.validateConfig(appConfig)
   * if (errors.length > 0) {
   *   console.error('配置验证失败:', errors)
   * }
   * ```
   */
  static validateConfig(config: AppConfig): string[] {
    const errors: string[] = []

    // 统一多服务商：若启用代理但所有 provider 池均为空，仅作提醒（不强制报错）
    if (config.proxy.enabled) {
      const providers = Array.isArray(config.proxy.providers) ? config.proxy.providers : []
      const provPools = providers
        .filter(p => p && (p.enabled !== false))
        .reduce((n, p) => n + (Array.isArray((p as any).pool) ? (p as any).pool.length : 0), 0)
      if (provPools === 0) {
        // 仅提示：前端可通过“拉取代理池”补全
        // errors.push('代理已启用但 providers 池为空')
      }
    }

    if (config.proxy.enabled && config.proxy.validation?.enabled) {
      if (!config.proxy.validation.test_url) {
        errors.push('代理校验已启用但未配置 test_url')
      }
      if (!config.proxy.validation.timeout_seconds || config.proxy.validation.timeout_seconds < 3) {
        errors.push('代理校验超时需 >= 3 秒')
      }
    }

    if (config.proxy.blacklist_ttl_minutes !== undefined && config.proxy.blacklist_ttl_minutes <= 0) {
      errors.push('黑名单TTL必须为正数（分钟）')
    }

    return errors
  }
}
